package cn.ilikes.tools.nosql.jpa;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceUnitInfo;

import org.slf4j.Logger;

import cn.ilikes.tools.logs.Loggerfactory;
import cn.ilikes.tools.nosql.jpa.configs.JPASQLPersistenceUnitMetadata;
import cn.ilikes.tools.nosql.jpa.configs.envs.sys.PersistenceUnitConfigsPaser;
import cn.ilikes.tools.nosql.jpa.envs.JPASQLPersistenceUnitEnvConfigFactory;
import cn.ilikes.tools.nosql.jpa.envs.JPASQLSystemEnvConfigFactory;
import cn.ilikes.tools.nosql.jpa.persistences.DefaultJPASQLEntityManagerFactory;

/**
 * 
 * @author fack
 * 
 */
public class JPASQLPersistenceProvider extends AbJPASQLPersistenceProvider {

	private static Map<String, DefaultJPASQLEntityManagerFactory> entityManagerFactoryMap = new HashMap<String, DefaultJPASQLEntityManagerFactory>();

	private Logger logger = Loggerfactory.instance(AbJPASQLPersistenceProvider.class);

	public final static String DEFAULT_PERSISTENCE_XML_LOCATION = "META-INF/persistence.xml";

	private JPASQLSystemEnv systemEnv = new JPASQLSystemEnv();

	public JPASQLPersistenceProvider() {
		initSys();
	}

	private void initSys() {
		JPASQLSystemEnvConfigFactory systemEnvConfigFactory = new JPASQLSystemEnvConfigFactory();
		systemEnvConfigFactory.init(systemEnv);
	}

	@SuppressWarnings("unchecked")
	@Override
	public EntityManagerFactory createEntityManagerFactory(String persistenceUnitsName, Map persistenceUnitsConfig) {
		Loggerfactory.info(logger, " create entity manager  factory  persistence units  name : " + persistenceUnitsName);
		DefaultJPASQLEntityManagerFactory entityManagerFactory = entityManagerFactoryMap.get(persistenceUnitsName);
		if (entityManagerFactory == null) {
			synchronized (entityManagerFactoryMap) {
				PersistenceUnitConfigsPaser persistenceUnitPaserConfigs = new PersistenceUnitConfigsPaser(systemEnv, DEFAULT_PERSISTENCE_XML_LOCATION, new Properties());
				JPASQLPersistenceUnitMetadata persistenceUnitMetadata = persistenceUnitPaserConfigs.selectJPASQLPersistenceUnitMetadata(persistenceUnitsName);
				entityManagerFactory = createEntityManagerFactory(persistenceUnitsName, persistenceUnitMetadata, persistenceUnitsConfig);
			}
		}
		return entityManagerFactory;

	}

	@SuppressWarnings("unchecked")
	private DefaultJPASQLEntityManagerFactory createEntityManagerFactory(String persistenceUnitsName, JPASQLPersistenceUnitMetadata persistenceUnitMetadata, Map properties) {
		Properties persistenceUnitsProperties = new Properties();
		if (properties == null)
			properties = new HashMap();
		persistenceUnitsProperties.putAll(properties);

		JPASQLPersistenUnitEnv hbasePersistenUnitEnv = initHbasePersistenceUnitEnv(persistenceUnitsName, persistenceUnitsProperties, persistenceUnitMetadata);
		DefaultJPASQLEntityManagerFactory entityManagerFactory = new DefaultJPASQLEntityManagerFactory(persistenceUnitsProperties, hbasePersistenUnitEnv);
		entityManagerFactory.init();
		entityManagerFactoryMap.put(persistenceUnitsName, entityManagerFactory);
		return entityManagerFactory;
	}

	@Override
	@SuppressWarnings("unchecked")
	public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo arg0, Map arg1) {
		String persistenceUnitsName = arg0.getPersistenceUnitName();
		Loggerfactory.info(logger, " create entity manager  factory  persistence units  name : " + arg0.getPersistenceUnitName());
		DefaultJPASQLEntityManagerFactory entityManagerFactory = entityManagerFactoryMap.get(persistenceUnitsName);
		if (entityManagerFactory == null) {
			synchronized (entityManagerFactoryMap) {
				JPASQLPersistenceUnitMetadata persistenceUnitMetadata = (JPASQLPersistenceUnitMetadata) arg0;
				//init
				entityManagerFactory = createEntityManagerFactory(arg0.getPersistenceUnitName(), persistenceUnitMetadata, arg1);
			}
		}
		return entityManagerFactory;
	}

	private JPASQLPersistenUnitEnv initHbasePersistenceUnitEnv(String persistenceUnitsName, Properties configs, JPASQLPersistenceUnitMetadata persistenceUnitMetadata) {
		JPASQLPersistenceUnitEnvConfigFactory persistenceUnitEnvConfigFactory = new JPASQLPersistenceUnitEnvConfigFactory(persistenceUnitsName, systemEnv, configs, persistenceUnitMetadata);
		return persistenceUnitEnvConfigFactory.create();
	}

}
